import 'package:dio/dio.dart';
import 'package:flutter_share/constants/index.dart';
import 'package:flutter_share/utils/Emitter.dart';
import 'package:flutter_share/utils/toast.dart';
import 'package:flutter_share/utils/token_manager.dart';

class RequestDio {
  final Dio _dio = Dio();
  RequestDio() {
    // 设置请求的根路径
    // _dio.options.baseUrl = GlobalVariable.BASE_URL;
    // // 设置请求的连接超时时间
    // _dio.options.connectTimeout =
    //     const Duration(seconds: GlobalVariable.NET_WORK_TIME);
    // // 设置请求的读取超时时间
    // _dio.options.receiveTimeout =
    //     const Duration(seconds: GlobalVariable.NET_WORK_TIME);

    // 设置请求的根路径，连接超时时间，读取超时时间（flutter特有语法）
    _dio.options
      ..baseUrl = GlobalVariable.BASE_URL
      ..connectTimeout = const Duration(seconds: GlobalVariable.NET_WORK_TIME)
      ..receiveTimeout = const Duration(seconds: GlobalVariable.NET_WORK_TIME);

    // 添加拦截器
    _interceptors();
  }

  // 拦截器
  void _interceptors() {
    _dio.interceptors.add(InterceptorsWrapper(
      // 请求拦截器
      onRequest: (options, handler) {
        // todo:在请求头中添加token
        final token = tokenManager.getToken();
        // 如果存在token 则添加到请求头
        if (token.isNotEmpty) {
          options.headers['Authorization'] = 'Bearer $token';
        }
        handler.next(options);
      },
      // 响应拦截器 200 >= HTTP状态码 < 300
      onResponse: (response, handler) {
        // todo:提取后端数据
        // todo:HTTP状态码判断
        // todo:业务状态码判断
        handler.next(response);
      },
      // 错误拦截器 400 <= HTTP状态码 < 500
      onError: (error, handler) async {
        if (error.response?.statusCode == 401) {
          // 删除 token
          //tokenManager.deleteToken();

          // 非页面，无法获取到 context，所以无法跳转
          // Navigator.pushNamed(context, '/login');
          // 触发退出登录事件，目的是调用页面跳转
          //eventBus.fire(LogoutEvent());
          // 1. 获取刷新 token
          String refreshToken = tokenManager.getRefreshToken();
          // 如果刷新 token 不存在，则退出登录
          if (refreshToken.isEmpty) {
            // 删除 token
            tokenManager.deleteToken();
            // 非页面，无法获取到 context，所以无法跳转
            // Navigator.pushNamed(context, '/login');
            // 触发退出登录事件，目的是调用页面跳转
            eventBus.fire(LogoutEvent());
          } else {
            // 如果有刷新 token，重新换取新的访问 token
            final isOk = await _refreshToken();
            // 无感重新发送请求
            if (isOk) {
              // 重新发送请求
              final res = await _dio.fetch(error.requestOptions);
              handler.resolve(res); // 标记为成功
              return;
            } else {
              tokenManager.deleteToken();
              eventBus.fire(LogoutEvent());
            }
          }
        }
        // todo:错误处理
        PromptAction.showError(error.response?.data["messgae"] ?? "请求失败");
        return handler.next(error);
      },
    ));
  }

  // 刷新 token 核心业务
  Future<bool> _refreshToken() async {
    try {
      // 1. 获取刷新 token
      String refreshToken = tokenManager.getRefreshToken();
      // 2. 创建新的请求对象
      Dio dio = Dio();
      dio.options
        ..baseUrl = GlobalVariable.BASE_URL
        ..connectTimeout = const Duration(seconds: GlobalVariable.NET_WORK_TIME)
        ..receiveTimeout = const Duration(seconds: GlobalVariable.NET_WORK_TIME)
        ..headers['Authorization'] = 'Bearer $refreshToken';
      // 3. 请求刷新 token 接口
      final res = await dio.post('/refreshToken');
      // 4. 判断是否刷新成功
      if (res.data['code'] == GlobalVariable.SUCCESS_CODE) {
        // 5. 更新 token
        tokenManager.setToken(
          res.data['data']['token'],
          res.data['data']['refreshToken'],
        );
        // 返回 true，表示 token 续期成功
        return true;
      } else {
        return false;
      }
    } catch (e) {
      return false;
    }
  }

  // 请求方法二次封装
  Future get(String url, {Map<String, dynamic> params = const {}}) async {
    final response = await _dio.get(url, queryParameters: params);
    return _handleResponse(response);
  }

  Future post(String url, {Map<String, dynamic> data = const {}}) async {
    final response = await _dio.post(url, data: data);
    return _handleResponse(response);
  }

  Future put(String url, {Map<String, dynamic> data = const {}}) async {
    final response = await _dio.put(url, data: data);
    return _handleResponse(response);
  }

  Future delete(String url, {Map<String, dynamic> data = const {}}) async {
    final response = await _dio.delete(url, data: data);
    return _handleResponse(response);
  }

  Future patch(String url, {Map<String, dynamic> data = const {}}) async {
    final response = await _dio.patch(url, data: data);
    return _handleResponse(response);
  }

   // 上传文件，参数格式为 FormData
  Future upload(String url, {FormData? data}) async {
    final response = await _dio.post(url, data: data);
    return _handleResponse(response);
  }
}

// 响应数据处理
_handleResponse(Response response) {
  // 检查业务状态码是否 10000 成功
  if (response.data['code'] == GlobalVariable.SUCCESS_CODE) {
    // 此时说明请求成功，返回正确的数据
    return response.data['data'];
  } else {
    PromptAction.showError(response.data["message"]);
  }
  throw Exception(response.data['message']);
}

// 单例(单个实例)模式
final requestDio = RequestDio();
